package mx.itesm.rmroman.proyectojuegomavi;

import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;

import org.andengine.audio.music.Music;
import org.andengine.audio.music.MusicFactory;
import org.andengine.audio.sound.Sound;
import org.andengine.audio.sound.SoundFactory;
import org.andengine.entity.IEntity;
import org.andengine.entity.modifier.DelayModifier;
import org.andengine.entity.modifier.JumpModifier;
import org.andengine.entity.modifier.ParallelEntityModifier;
import org.andengine.entity.modifier.RotationModifier;
import org.andengine.entity.modifier.ScaleModifier;
import org.andengine.entity.modifier.SequenceEntityModifier;
import org.andengine.entity.scene.background.AutoParallaxBackground;
import org.andengine.entity.scene.background.ParallaxBackground;
import org.andengine.entity.sprite.AnimatedSprite;
import org.andengine.entity.sprite.Sprite;
import org.andengine.input.touch.TouchEvent;
import org.andengine.opengl.texture.region.TiledTextureRegion;

import java.io.IOException;

import mx.itesm.rmroman.items.Roca;

/**
 * La escena que muestra información del juego
 * @author Roberto Martínez Román
 */
public class EscenaJuegoDos extends EscenaBase
{
    // Fondos para la animación de capas
    private Sprite fondoLejos;
    private Sprite fondoMedio;
    private Sprite fondoCerca;
    // Maneja las 3 imágenes de fondo
    AutoParallaxBackground fondo;

    // Sprite animado en la pantalla
    private AnimatedSprite perro;

    // Bandera para saber si el perro está saltando
    private boolean perroSaltando;

    // Marcador
    private EstadoJuego hud;

    // ENEMIGO, una roca
    private Roca roca;

    // ***** MUSICA *****
    private Music musicaFondo;
    private Sound efectoSonido;
    private Sound efectoExplosion;  // Ver cargarSonidos
    // Banderas
    private boolean chocando=false;
    private boolean pasaRoca=false;
    private float deltaRoca=6;
    private boolean termina = false;

    @Override
    public void crearEscena() {

        perroSaltando=false;
        agregarFondoAnimado();
        agregarPerroAnimado();
        agregarEstado();
        agregarRoca(); // Enemigo
        // MUSICA
        cargarSonidos();
    }

    // Carga los recursos de sonido
    private void cargarSonidos() {
        // ***** Música de fondo
        try {
            musicaFondo = MusicFactory.createMusicFromAsset(admRecursos.engine.getMusicManager(),
                    admRecursos.actividadJuego, "sonidos/demo.ogg");
        }
        catch (IOException e) {
            Log.i("cargarSonidos","No se puede cargar demo.ogg");
        }
        // Reproducir
        musicaFondo.setLooping(true);
        musicaFondo.play();

        // Efecto de sonido
        try {
            efectoSonido = SoundFactory.createSoundFromAsset(admRecursos.engine.getSoundManager(),
                    admRecursos.actividadJuego, "sonidos/bark.wav");
            efectoExplosion = SoundFactory.createSoundFromAsset(admRecursos.engine.getSoundManager(),
                    admRecursos.actividadJuego, "sonidos/choque.mp3");
        } catch (final IOException e) {
            Log.i("cargarSonidos","No se puede cargar efecto de sonido");
        }
        efectoExplosion.setVolume(0.5f);    // Volumen de este archivo
        // *** Ver onManagedUpdate, onSceneTouchEvent, onBackKeyPressed, liberarEscena
    }


    private void agregarRoca() {
        roca = new Roca(ControlJuego.ANCHO_CAMARA,admRecursos.regionFondoCerca.getHeight(),
                admRecursos.regionRoca,admRecursos.vbom);
        attachChild(roca.getSpriteRoca());
    }

    private void agregarEstado() {
        hud = new EstadoJuego(admRecursos.engine,admRecursos.actividadJuego);
        admRecursos.camara.setHUD(hud);

        // Para marcador más alto. PRIMERO lee el marcador anterior
        SharedPreferences preferencias = admRecursos.actividadJuego.getSharedPreferences(
                "MarcadorMasAlto", Context.MODE_PRIVATE);
        int ultimoMarcador = preferencias.getInt("alto",0);
        hud.setMarcadorMasAlto(ultimoMarcador);
    }

    // Agrega a la escena el sprite animado
    private void agregarPerroAnimado() {
        TiledTextureRegion regionPerro = admRecursos.regionPerroAnimado;
        perro = new AnimatedSprite(ControlJuego.ANCHO_CAMARA/2,regionPerro.getHeight(),
                regionPerro,admRecursos.vbom);
        // Arreglo de tiempos para los frames
        long tiempos[] = new long[23];
        for(int i=0; i<tiempos.length; i++) {
            tiempos[i] = 40;
        }

        perro.animate(tiempos,0,tiempos.length-1,true);   // Camina normal
        attachChild(perro);
    }

    // Background ANIMADO con varias CAPAS
    private void agregarFondoAnimado() {

        float xLejos = admRecursos.regionFondoLejos.getWidth()/2;
        float xMedio = admRecursos.regionFondoMedio.getWidth()/2;
        float xCerca = admRecursos.regionFondoCerca.getWidth()/2;

        float y = ControlJuego.ALTO_CAMARA/2;
        float yCerca = admRecursos.regionFondoCerca.getHeight()/2;

        fondoLejos = new Sprite(xLejos,y,admRecursos.regionFondoLejos,admRecursos.vbom);
        fondoMedio = new Sprite(xMedio,y,admRecursos.regionFondoMedio,admRecursos.vbom);
        fondoCerca = new Sprite(xCerca,yCerca,admRecursos.regionFondoCerca,admRecursos.vbom);

        // Se agregan las capas individuales al autoParallax
        fondo = new AutoParallaxBackground(0,0,0,10);
        fondo.attachParallaxEntity(new ParallaxBackground.ParallaxEntity(-2,fondoLejos));
        fondo.attachParallaxEntity(new ParallaxBackground.ParallaxEntity(-4,fondoMedio));
        fondo.attachParallaxEntity(new ParallaxBackground.ParallaxEntity(-8,fondoCerca));

        setBackground(fondo);
        setBackgroundEnabled(true);
    }

    // El ciclo principal de la escena
    @Override
    protected void onManagedUpdate(float pSecondsElapsed) {
        super.onManagedUpdate(pSecondsElapsed);
        //hud.aumentarMarcador(1);  // Ahora solo si la roca pasó al perro
        // Anima la roca...

        if (deltaRoca<18) {
            deltaRoca += pSecondsElapsed / 7; // Para que sea cada vez más rápido
        }
        if (!termina) {
            roca.mover(-deltaRoca, 0);
            roca.girar(5);
            if (roca.getSpriteRoca().getX() < 0) {
                float xAzar = (float)(Math.random()*200);
                roca.getSpriteRoca().setX(ControlJuego.ANCHO_CAMARA+xAzar);
                pasaRoca = false;   // Para contar puntos cuando pasa la roca
            }
            if (perro.collidesWith(roca.getSpriteRoca()) && !chocando) {
                chocando = true;  // invulnerable por ahora
                roca.getSpriteRoca().setX(ControlJuego.ANCHO_CAMARA + 3 * roca.getSpriteRoca().getWidth());    // Lo reinicia
                // Pierde una vida!!!
                // Descontar vidas
                hud.disminuirVidas(1);
                efectoExplosion.play();     // Efecto de explosión  :)
                ScaleModifier escalaPequeno = new ScaleModifier(0.3f, 1, 0.1f);
                ScaleModifier escalaGrande = new ScaleModifier(0.3f, 0.1f, 1f);
                SequenceEntityModifier secuencia = new SequenceEntityModifier(escalaPequeno, escalaGrande) {
                    @Override
                    protected void onModifierFinished(IEntity pItem) {
                        super.onModifierFinished(pItem);
                        chocando = false; // deja de ser vulnerable
                    }
                };
                perro.registerEntityModifier(secuencia);
            }
        }

        if ( (roca.getSpriteRoca().getX() < perro.getX()-perro.getWidth()/2) && !pasaRoca ) {
            // Ya lo pasó, aumentar marcador
            hud.aumentarMarcador(1);
            pasaRoca=true;
        }

        // Pierde???
        if (hud.getVidas()<=0 && !termina) {
            termina = true;
            efectoSonido.setRate(0.5f);
            efectoSonido.play();
            DelayModifier espera = new DelayModifier(0.7f);
            //ScaleModifier escalaPequeno = new ScaleModifier(0.2f,1,0.1f);
            RotationModifier rotar = new RotationModifier(1.5f,0,360);
            ScaleModifier escalaGrande = new ScaleModifier(1.5f,0.1f,20f);
            ParallelEntityModifier paralelo = new ParallelEntityModifier(rotar,escalaGrande);
            SequenceEntityModifier secuencia = new SequenceEntityModifier(espera,paralelo) {
                @Override
                protected void onModifierFinished(IEntity pItem) {
                    super.onModifierFinished(pItem);
                    onBackKeyPressed();
                }
            };
            perro.registerEntityModifier(secuencia);
        }
    }

    @Override
    public boolean onSceneTouchEvent(TouchEvent pSceneTouchEvent) {
        float x = pSceneTouchEvent.getX();

        if (pSceneTouchEvent.isActionDown() && x<ControlJuego.ANCHO_CAMARA/2 && !perroSaltando) {
            perroSaltando=true;
            // ***** Reproduce el efecto de sonido *****
            efectoSonido.play();
            // Saltar
            float xa = perro.getX();
            float ya = perro.getY();
            float xn = xa;
            float yn = ya;
            RotationModifier rotacion = new RotationModifier(1,360,0);
            JumpModifier salto = new JumpModifier(1,xa,xn,ya,yn,-200);
            ParallelEntityModifier paralelo = new ParallelEntityModifier(rotacion,salto) {
                @Override
                protected void onModifierFinished(IEntity pItem) {
                    super.onModifierFinished(pItem);
                    perroSaltando=false;
                }
            };
            perro.registerEntityModifier(paralelo);
        }

        return super.onSceneTouchEvent(pSceneTouchEvent);
    }

    // El usuario oprime el botón de BACK; regresar al menú principal
    @Override
    public void onBackKeyPressed() {
        // Regresar al MENU principal
        admRecursos.camara.setHUD(null);    // Quita el HUD
        musicaFondo.stop();
        efectoSonido.stop();

        revisarMarcador(); // Para ver si hay un NUEVO marcador MAS ALTO

        admEscenas.crearEscenaMenu();
        admEscenas.setEscena(TipoEscena.ESCENA_MENU);
        admEscenas.liberarEscenaJuegoDos();
    }

    private void revisarMarcador() {
        int masAlto = hud.getMarcadorMasAlto();
        int puntos = hud.getMarcador();
        if (puntos>=masAlto) {
            // guardarlo en las preferencias
            SharedPreferences preferencias = admRecursos.actividadJuego.getSharedPreferences(
              "MarcadorMasAlto",Context.MODE_PRIVATE);
            SharedPreferences.Editor editor = preferencias.edit();
            editor.putInt("alto",masAlto);
            editor.commit();
        }
    }

    @Override
    public TipoEscena getTipoEscena() {
        return TipoEscena.ESCENA_JUEGO_DOS;
    }

    @Override
    public void liberarEscena() {
        efectoSonido.release(); // Libera los sonidos
        efectoExplosion.release();
        musicaFondo.release();

        this.detachSelf();      // La escena misma se desconecta del engine
        this.dispose();         // Libera la memoria
    }

    public Music getMusicaFondo() {
        return musicaFondo;
    }
}
